package view
{
	import controllers.ImageManipulationState;
	
	import events.*;
	import events.MoveFocusEvent;
	
	import flash.events.MouseEvent;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.geom.Vector3D;
	import flash.utils.flash_proxy;
	
	import models.Model;
	
	import mx.binding.utils.BindingUtils;
	import mx.binding.utils.ChangeWatcher;
	import mx.controls.Image;
	import mx.events.DragEvent;
	import mx.events.MoveEvent;
	import mx.managers.DragManager;
	
	import skins.ImageManipulatorSkin;
	
	import spark.components.supportClasses.SkinnableComponent;
	import spark.primitives.Rect;

	[Event(name="transformImage", type="events.TransformImageEvent")]
	[Event(name="changeImageState", type="events.ChangeImageStateEvent")]
	public class ImageMainipulator extends SkinnableComponent
	{		
		private var oldMouseCoords:Vector3D = new Vector3D(0,0,0);
		private var slideChanged:Boolean = true;
		[Bindable]
		public var _model:Model;
		[Bindable]
		public var manipulated:Image;
		
		private var currentSlideWatcher:ChangeWatcher;
		
		[Embed(source="../resourses/cursors/move.PNG")]
		private var MoveCursor:Class;
		[Embed(source="../resourses/cursors/resize.PNG")]
		private var ResizeCursor:Class;
		[Embed(source="../resourses/cursors/rotate.png")]
		private var RotateCursor:Class;
		private var CursorID:int=10;
		
		public function set model(value:Model):void
		{
			if (_model != null)
			{
				currentSlideWatcher.unwatch();
			}
			_model = value;
			currentSlideWatcher = BindingUtils.bindSetter(setCurrentSlide, _model, "currentSlide");
		}
		public function get model():Model
		{
			return _model;
		}
		public function ImageMainipulator()
		{
			super();					
			addEventListener(MouseEvent.MOUSE_DOWN,changeContainerStateHandler);
			addEventListener(MouseEvent.MOUSE_UP,mouseUpHandler);
			addEventListener(MouseEvent.MOUSE_MOVE,rotateImageHandler);	
			
			addEventListener(DragEvent.DRAG_ENTER,dragEnterHandler);		
			addEventListener(DragEvent.DRAG_DROP,dragDropHandler);
			addEventListener(MouseEvent.MOUSE_OUT,mouseOutHandler);			
		}			
		
		private function updateSlide():void
		{
			slideChanged = true;
			invalidateProperties();
		}
		
		protected override function childrenCreated():void
		{
			super.childrenCreated();
		}
		
		private function setCurrentSlide(value:Image):void
		{
			updateSlide();
		}
		protected override function commitProperties():void
		{
			super.commitProperties();
			if(slideChanged)
			{
				slideChanged = false;
				if (manipulated!=null)
				{
					manipulated.removeEventListener(MouseEvent.MOUSE_MOVE,moveImageHandler);
					manipulated.removeEventListener(MouseEvent.MOUSE_DOWN,changeImageStateHandler);
				}
				manipulated = model.currentSlide;
				manipulated.addEventListener(MouseEvent.MOUSE_MOVE,moveImageHandler);				
				manipulated.addEventListener(MouseEvent.MOUSE_DOWN,changeImageStateHandler);
			}
		}
		
		private function changeImageStateHandler(event:MouseEvent):void
		{			
			var oldImageProperty:Vector3D;
			oldMouseCoords = new Vector3D(event.stageX,event.stageY,0);
			if (resizeAreaContains(new Point(event.stageX,event.stageY)))
			{						
				oldImageProperty = new Vector3D(manipulated.scaleX,manipulated.scaleY);
				dispatchEvent(
					new ChangeImageStateEvent(ChangeImageStateEvent.CHANGEIMGESTATE,
											  oldImageProperty,ImageManipulationState.RESIZE ))
			}			
			else 
			{			
				oldImageProperty = new Vector3D(manipulated.x,manipulated.y,0) ;
				dispatchEvent(
					new ChangeImageStateEvent(ChangeImageStateEvent.CHANGEIMGESTATE,
						oldImageProperty,ImageManipulationState.MOVE ))			
			}
			event.stopImmediatePropagation();
		}
		
		protected function changeContainerStateHandler(event:MouseEvent):void
		{						
			var oldImageProperty:Vector3D = new Vector3D(manipulated.rotationX,manipulated.rotationY,rotationZ);
			dispatchEvent(
				new ChangeImageStateEvent(ChangeImageStateEvent.CHANGEIMGESTATE,
					oldImageProperty,ImageManipulationState.ROTATE ))
		}
		
		private function moveImageHandler(event:MouseEvent):void
		{				
			var delta:Vector3D = new Vector3D(event.stageX-oldMouseCoords.x,event.stageY-oldMouseCoords.y);			
			if (resizeAreaContains(new Point(event.stageX,event.stageY)))
			{					
				cursorManager.removeCursor(CursorID);
				CursorID= cursorManager.setCursor(ResizeCursor);				
			}
			else
			{
				cursorManager.removeCursor(CursorID);
				CursorID= cursorManager.setCursor(MoveCursor);				
			}
			dispatchEvent(new TransformImageEvent(TransformImageEvent.TRANSFORM, delta));

			event.stopImmediatePropagation();		
		}		
		
		protected function rotateImageHandler(event:MouseEvent):void
		{			 
			cursorManager.removeCursor(CursorID);
			CursorID= cursorManager.setCursor(RotateCursor);
			
			var center:Point = manipulated.localToGlobal(new Point(0,0));
			var point:Point =  new Point(event.stageX,event.stageY);
			var delta:Vector3D = new Vector3D();
			delta.x =  point.x - center.x;
			delta.y = point.y - center.y;					
			dispatchEvent(new TransformImageEvent(TransformImageEvent.TRANSFORM, delta));
		}
		
		private function dragEnterHandler(event:DragEvent):void			
		{			
			DragManager.acceptDragDrop(event.currentTarget as ImageMainipulator);
		}
		
		private function dragDropHandler(event:DragEvent):void
		{
			var data:Object = event.dragSource.dataForFormat("itemsByIndex");					
			model.addImage(data[0] as Image);
			slideChanged = true;
			invalidateProperties();
		}		
		
		private function resizeAreaContains(point:Point):Boolean
		{
			var ResizeAreaSize:int = 10;
			var zero:Point =  manipulated.localToGlobal(new Point(0,0));

			var rect:Rectangle = new Rectangle(zero.x,zero.y,
				ResizeAreaSize,
				ResizeAreaSize);
			return rect.containsPoint(point);
		}		

		protected function mouseUpHandler(event:MouseEvent):void
		{
			dispatchEvent(
				new ChangeImageStateEvent(ChangeImageStateEvent.CHANGEIMGESTATE,
					new Vector3D(),ImageManipulationState.NONE ))
		}
		
		protected function mouseOutHandler(event:MouseEvent):void
		{
			cursorManager.removeCursor(CursorID);
		}
	}
}
